﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using IdentityMiddleware.IdentityProvider;
using IdentityMiddleware.IdentityProvider.Model;
using IdentityModel;
using IdentityServer4.AccessTokenValidation;
using IdentityServer4.Configuration;
using IdentityServer4.Hosting;
using IdentityServer4.Services;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Cors.Infrastructure;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using MySql.Data.MySqlClient;
using Swashbuckle.AspNetCore.Swagger;

namespace IdentityMiddleware
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            
            //添加MS的Identity实现
            services.AddIdentity<UserModel, RoleModel>(options =>
                {
                    // Password settings.
                    options.Password.RequireDigit = false;
                    options.Password.RequireLowercase = false;
                    options.Password.RequireNonAlphanumeric = false;
                    options.Password.RequireUppercase = false;
                    options.Password.RequiredLength = 6;
                    //options.Password.RequiredUniqueChars = 1;

                    // Lockout settings.
                    //options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
                    //options.Lockout.MaxFailedAccessAttempts = 5;
                    //options.Lockout.AllowedForNewUsers = true;
                    // User settings.
                    options.User.AllowedUserNameCharacters =
                        "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
                    //options.User.RequireUniqueEmail = false;
                })
                .AddDefaultTokenProviders();
            

            //添加实现Ms的Identity实现中需要用到的自定义存储实现
            string connectionString = Configuration.GetConnectionString("MySqlConnection");

            services.AddTransient<MySqlConnection>(e => new MySqlConnection(connectionString));
            services.AddTransient<UserTable>();
            services.AddTransient<RoleTable>();
            services.AddTransient<IUserStore<UserModel>, UserStore>();
            services.AddTransient<IUserClaimStore<UserModel>, UserStore>();
            services.AddTransient<IUserRoleStore<UserModel>, UserStore>();
            services.AddTransient<IUserPasswordStore<UserModel>, UserStore>();
            services.AddTransient<IRoleStore<RoleModel>, RoleStore>();
            //添加IdentityServer4
            services.AddIdentityServer()
                //添加储存和test
                .AddDeveloperSigningCredential()
                .AddInMemoryPersistedGrants()
                //添加资源
                .AddInMemoryApiResources(Config.GetApiResources(new MySqlConnection(connectionString),"select ClaimType from claim"))
                .AddInMemoryIdentityResources(Config.GetIdentityResources())
                //添加客户端
                .AddInMemoryClients(Config.GetClients())
                //添加用户
                .AddTestUsers(Config.GetUsers())
                .AddAspNetIdentity<UserModel>()/*.AddProfileService<ProfileServiceModel>()*/;
            
            services.AddAuthentication(options =>
                    {
                        options.DefaultAuthenticateScheme = IdentityServerAuthenticationDefaults.AuthenticationScheme;//"Bearer"
                        options.DefaultChallengeScheme = IdentityServerAuthenticationDefaults.AuthenticationScheme;//"Bearer"
                        options.DefaultForbidScheme = IdentityServerAuthenticationDefaults.AuthenticationScheme;//"Bearer"
                        options.DefaultSignInScheme=IdentityServerAuthenticationDefaults.AuthenticationScheme;//"Bearer"
                        options.DefaultSignOutScheme=IdentityServerAuthenticationDefaults.AuthenticationScheme;//"Bearer"
                        //options.DefaultAuthenticateScheme = IdentityServerAuthenticationDefaults.AuthenticationScheme;//"Bearer"
                    })
                .AddIdentityServerAuthentication(options =>
                {
                    options.Authority = "https://e-rewin.com:5005";
                    options.RequireHttpsMetadata = false;
                    options.ApiName = "UserManager";
                    options.RoleClaimType = JwtClaimTypes.Role;
                    options.NameClaimType = JwtClaimTypes.Name;
                });
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("UserManager", new Info { Title = "UserManager API", Version = "v1" });
                var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
                var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
                c.IncludeXmlComments(xmlPath);
                //c.DocumentFilter<TagDescriptionsDocumentFilter>();
                c.AddSecurityDefinition("oauth2", new OAuth2Scheme
                {
                    Type = "oauth2",
                    Flow = "password",
                    TokenUrl = "https://e-rewin.com:5005/connect/token",
                    Scopes = new Dictionary<string, string>
                    {
                        { "UserManager", "用户管理" },
                        {"openid","openid"},
                        {"profile","profile"}
                    }
                });
                c.DescribeAllEnumsAsStrings();
                c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>>
                {
                    { "oauth2", new[] { "UserManager" ,"openid","profile" } }
                });
            });
            services.AddAuthorization();
            services.AddCors(options =>
            {
                options.AddPolicy("AllowSpecificOrigin",
                    builder => builder.WithOrigins("https://bts_api.e-rewin.com:5000","http://bts_api.e-rewin.com:5000","https://bts_web.e-rewin.com:5010"));
            });
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseHsts();
            }
            
            //app.UseCors("AllowSpecificOrigin");
            //app.UseCors(builder => builder.WithOrigins("https://bts_api.e-rewin.com:5000","http://bts_api.e-rewin.com:5000","https://bts_web.e-rewin.com:5010").AllowAnyHeader().AllowAnyMethod().WithExposedHeaders("Content-Disposition"));
            app.UseCors(builder => builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod().WithExposedHeaders("Content-Disposition"));
            //app.UseCors(builder => builder.WithOrigins("https://bts_api.e-rewin.com:5000","http://bts_api.e-rewin.com:5000","https://bts_web.e-rewin.com:5010","https://e-rewin.com:5000","http://e-rewin.com:5010","https://e-rewin.com:5005","https://localhost:5000","https://localhost:5005").AllowAnyHeader().AllowAnyMethod().WithExposedHeaders("Content-Disposition"));
            app.UseIdentityServer();
            app.UseAuthentication();
            app.UseSwagger();
            app.UseSwaggerUI(c =>
            {
                c.SwaggerEndpoint("/swagger/UserManager/swagger.json", "UserManager Api");
                c.RoutePrefix = string.Empty;

            });
            
            //app.UseMvcWithDefaultRoute();
            app.UseMvc();
        }
    }
}
